package controllers

import (
	"errors"
	"go-api-demo/database"
	"go-api-demo/models"
	"net/http"
	"os"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

// Register godoc
// @Summary 用户注册
// @Description 注册新用户（自动加密密码）
// @Tags 用户模块
// @Accept json
// @Produce json
// @Param data body models.User true "用户注册信息（username, password）"
// @Success 200 {object} map[string]interface{} "注册成功返回用户ID和用户名"
// @Failure 400 {object} map[string]interface{} "参数错误"
// @Failure 409 {object} map[string]interface{} "用户已存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /register [post]
func Register(c *gin.Context) {
	var req models.User
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误: " + err.Error()})
		return
	}

	// 检查用户是否已存在
	var existing models.User
	if err := database.DB.Where("username = ?", req.Username).First(&existing).Error; err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "数据库查询失败"})
			return
		}
	} else {
		c.JSON(http.StatusConflict, gin.H{"error": "用户已存在"})
		return
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "密码加密失败"})
		return
	}

	user := models.User{
		Username: req.Username,
		Password: string(hashedPassword),
	}

	if err := database.DB.Create(&user).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "注册失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "注册成功",
		"user": gin.H{
			"id":       user.ID,
			"username": user.Username,
		},
	})
}

var jwtSecret = []byte(os.Getenv("JWT_SECRET"))

// Login godoc
// @Summary 用户登录
// @Description 用户登录并返回 JWT Token
// @Tags 用户模块
// @Accept json
// @Produce json
// @Param data body models.User true "用户登录信息（username, password）"
// @Success 200 {object} map[string]interface{} "登录成功返回Token"
// @Failure 400 {object} map[string]interface{} "参数错误"
// @Failure 401 {object} map[string]interface{} "用户不存在或密码错误"
// @Failure 500 {object} map[string]interface{} "生成Token失败"
// @Router /login [post]
func Login(c *gin.Context) {
	var req models.User
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}

	// 查找用户
	var user models.User
	if err := database.DB.Where("username = ?", req.Username).First(&user).Error; err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "用户不存在"})
		return
	}

	// 校验密码
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "密码错误"})
		return
	}

	// 生成 JWT
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"user_id":  user.ID,
		"username": user.Username,
		"exp":      time.Now().Add(time.Hour * 24).Unix(), // 过期时间：24小时
	})

	tokenString, err := token.SignedString(jwtSecret)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "生成 Token 失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "登录成功",
		"token":   tokenString,
	})
}
